/*
 *                        .::::.
 *                      .::::::::.
 *                     :::::::::::
 *                  ..:::::::::::'
 *               '::::::::::::'
 *                 .::::::::::
 *            '::::::::::::::..
 *                 ..::::::::::::.
 *               ``::::::::::::::::
 *                ::::``:::::::::'        .:::.
 *               ::::'   ':::::'       .::::::::.
 *             .::::'      ::::     .:::::::'::::.
 *            .:::'       :::::  .:::::::::' ':::::.
 *           .::'        :::::.:::::::::'      ':::::.
 *          .::'         ::::::::::::::'         ``::::.
 *      ...:::           ::::::::::::'              ``::.
 *     ````':.          ':::::::::'                  ::::..
 *                        '.:::::'                    ':'````..
 *
 * @Author: byx
 * @Date: 2022-08-06 13:08:16
 * @LastEditors: byx
 * @LastEditTime: 2022-10-17 21:44:00
 * @version: 1.0
 * @Descripttion: wwww.byx1024.top
 */
import { getNewCartGoods, mergeLocalCart, findCart, insertCart, deleteCart, updateCart, checkAllCart } from '@/api/cart'
import Message from '@/components/library/Message'

// 购物车状态
export default {
  namespaced: true,
  state: () => {
    return {
      // 购物车商品列表
      list: []
    }
  },
  getters: {
    // Ⅰ类：有效商品列表
    validList(state) {
      return state.list.filter((item) => item.stock > 0 && item.isEffective)
    },
    // Ⅰ类：有效商品件数
    validTotal(state, getters) {
      return getters.validList.reduce((p, c) => p + c.count, 0)
    },
    // Ⅰ类：有效商品总金额
    validAmount(state, getters) {
      // return getters.validList.reduce((p, c) => p + c.nowPrice * 100 * c.count, 0) / 100
      // return (getters.validList.reduce((p, c) => p + c.nowPrice * 100 * c.count, 0) / 100).toFixed(2)
      return getters.validList.reduce((p, c) => p + Math.round(c.nowPrice * 100) * c.count, 0) / 100
    },
    // Ⅱ类：无效商品列表
    invalidList(state) {
      return state.list.filter((item) => !(item.stock > 0 && item.isEffective))
    },
    // Ⅱ类：选中商品列表
    selectedList(state, getters) {
      return getters.validList.filter((item) => item.selected)
    },
    // Ⅱ类：选中商品件数
    selectedTotal(state, getters) {
      return getters.selectedList.reduce((p, c) => p + c.count, 0)
    },
    // Ⅱ类：选中商品总金额
    selectedAmount(state, getters) {
      return getters.selectedList.reduce((p, c) => p + c.nowPrice * 100 * c.count, 0) / 100
    },
    // Ⅱ类：是否全选
    isCheckAll(state, getters) {
      return getters.validList.length === getters.selectedList.length && getters.selectedList.length !== 0
    }
  },
  mutations: {
    // 1、加入购物车
    insertCart(state, payload) {
      // 约定加入购物车字段必须和后端保持一致 payload对象 的字段
      // 它们是：id skuId name attrsText picture price nowPrice selected stock count isEffective
      // 插入数据规则：
      // 1. 先找下是否有相同商品
      // 2. 如果有相同的商品，查询它的数量，累加到payload上，再保存最新位置，原来商品需要删除
      // 3. 如果没有相同商品，保存在最新位置即可
      const sameIndex = state.list.findIndex((goods) => goods.skuId === payload.skuId)
      if (sameIndex > -1) {
        const count = state.list[sameIndex].count
        payload.count += count
        // 删除原来
        state.list.splice(sameIndex, 1)
      }
      // 追加新的
      state.list.unshift(payload)
    },
    // 2、更新&修改购物车商品
    updateCart(state, goods) {
      // goods 商品信息：nowPrice stock isEffective
      // goods 商品对象的字段不固定，对象中不是有哪些字段就改哪些字段，字段的值合理才改/goods有的信息才去修改。
      // goods 商品对象 必需有SKUID，才能找到对应的商品信息
      const updateGoods = state.list.find((item) => item.skuId === goods.skuId)
      for (const key in goods) {
        if (goods[key] !== undefined && goods[key] !== null && goods[key] !== '') {
          updateGoods[key] = goods[key]
        }
      }
    },
    // 3、删除购物车商品
    deleteCart(state, skuId) {
      const index = state.list.findIndex((item) => item.skuId === skuId)
      state.list.splice(index, 1)
    },
    // 4、设置购物车（清空&设置）
    setCart(state, payload) {
      // payload 为空数组，清空。为有值数组，设置。
      state.list = payload
    }
  },
  actions: {
    // 1、加入购物车
    insertCartActn(ctx, goods) {
      return new Promise((resolve, reject) => {
        if (ctx.rootState.user.profile.token) {
          // 2.1、已登录（调用登录后的加入购物车API接口）
          insertCart(goods)
            .then(() => {
              // 1.加入成功后，继续调用获取购物车列表API接口
              return findCart()
            })
            .then((data) => {
              // 2.将获取到的商品数据，设置到购物车列表
              ctx.commit('setCart', data.result)
              resolve()
            })
        } else {
          // 2.1、未登录（直接调用mutations->insertCart方法即可）
          ctx.commit('insertCart', goods)
          resolve()
        }
      })
    },
    // 2、更新商品列表（未登录&登录后）
    findCartActn(ctx) {
      return new Promise((resolve, reject) => {
        if (ctx.rootState.user.profile.token) {
          // 已登录（调用登录后的获取购物车列表API接口）
          findCart().then((data) => {
            ctx.commit('setCart', data.result)
            resolve()
          })
        } else {
          // 未登录
          // 同时发送请求（有几个商品发几个请求）等所有请求成功，一并去修改本地数据。
          // Promise.all(promise数组).then((dataList)=>{})  同时发请求，所有请求成功，得到所有成功结果
          // Promise.resolve() Promise.reject() new Promise()
          // Promise.race(promise数组).then((data)=>{}) 同时发请求，最快的请求成功，得到成功结果
          const promiseArr = ctx.state.list.map((goods) => {
            return getNewCartGoods(goods.skuId)
          })
          // dataList成功结果的集合，数据顺序和promiseArr顺序一致，它又是根据state.list而来
          Promise.all(promiseArr)
            .then((dataList) => {
              // 更新本地购物车
              dataList.forEach((data, i) => {
                ctx.commit('updateCart', { skuId: ctx.state.list[i].skuId, ...data.result })
              })
              // 调用resolve代表操作成功
              resolve()
            })
            .catch((e) => {
              reject(e)
            })
        }
      })
    },
    // 3、删除购物车商品
    deleteCartActn(ctx, skuId) {
      return new Promise((resolve, reject) => {
        if (ctx.rootState.user.profile.token) {
          // 登录（调用登录后的删除商品API接口）
          deleteCart([skuId])
            .then(() => {
              // 1.删除成功后，继续调用获取购物车列表API接口
              return findCart()
            })
            .then((data) => {
              // 2.将获取到的商品数据，设置到购物车列表
              ctx.commit('setCart', data.result)
              resolve()
            })
        } else {
          // 未登录 本地
          ctx.commit('deleteCart', skuId)
          resolve()
        }
      })
    },
    // 2、修改商品列表（单选，数量）
    updateCartActn(ctx, goods) {
      // goods 中：必须有skuId，其他想修改的属性 selected  count
      return new Promise((resolve, reject) => {
        if (ctx.rootState.user.profile.token) {
          // 登录（调用登录后的修改购物车商品API接口）
          // console.log(goods)
          // {skuId: '300238781', count: 14}
          // {skuId: '300238781', selected: false}
          updateCart(goods)
            .then(() => {
              // 1.删除成功后，继续调用获取购物车列表API接口
              return findCart()
            })
            .then((data) => {
              // 2.将获取到的商品数据，设置到购物车列表
              ctx.commit('setCart', data.result)
              resolve()
            })
        } else {
          // 未登录 本地
          ctx.commit('updateCart', goods)
          resolve()
        }
      })
    },
    // 4、做有效商品的全选&反选
    checkAllCartActn(ctx, selected) {
      return new Promise((resolve, reject) => {
        if (ctx.rootState.user.profile.token) {
          // 登录（调用登录后的全部选中&取消全选API接口）
          // 1.有效商品列表
          const ids = ctx.getters.validList.map((item) => item.skuId)
          // 2.全部选中&取消全选(api)
          checkAllCart({ selected, ids })
            .then(() => {
              // 获取购物车列表(api)
              return findCart()
            })
            .then((data) => {
              // 设置购物车
              ctx.commit('setCart', data.result)
              resolve()
            })
        } else {
          // 未登录 本地
          // 1. 获取有效的商品列表，遍历的去调用修改mutations即可
          ctx.getters.validList.forEach((item) => {
            ctx.commit('updateCart', { skuId: item.skuId, selected })
          })
          resolve()
        }
      })
    },
    // 5、批量删除选中商品,也支持清空无效商品
    batchDeleteCartActn(ctx, isClear) {
      return new Promise((resolve, reject) => {
        if (ctx.rootState.user.profile.token) {
          // 登录（调用登录后的删除商品API接口）
          // 1.得到需要删除的商品列表（失效，选中）的skuId集合
          const ids = ctx.getters[isClear ? 'invalidList' : 'selectedList'].map((item) => item.skuId)
          if (ids.length === 0) return Message({ text: '请至少勾选一件商品！' })
          // 2.调用删除接口
          deleteCart(ids)
            .then(() => {
              // 1.删除成功后，继续调用获取购物车列表API接口
              return findCart()
            })
            .then((data) => {
              // 2.将获取到的商品数据，设置到购物车列表
              ctx.commit('setCart', data.result)
              resolve()
            })
        } else {
          // 未登录 本地
          // 1. 获取选中商品列表，进行遍历调用deleteCart mutataions函数
          // isClear 未 true  删除失效商品列表，否则事选中的商品列表
          ctx.getters[isClear ? 'invalidList' : 'selectedList'].forEach((item) => {
            ctx.commit('deleteCart', item.skuId)
          })
          resolve()
        }
      })
    },
    // 6、修改sku规格函数
    updateCartSkuActn(ctx, { oldSkuId, newSku }) {
      return new Promise((resolve, reject) => {
        if (ctx.rootState.user.profile.token) {
          // 登录
          // 1. 获取原先商品信息
          // 2. 删除原先商品(oldSkuId)
          // 3. 获取修改的skuId 和 原先商品数量 做一个加入购物车操作
          // 4. 更新列表
          const oldGoods = ctx.state.list.find((item) => item.skuId === oldSkuId)
          // 删除旧商品(api)
          deleteCart([oldSkuId])
            .then(() => {
              // 加入购物车(api)
              return insertCart({ skuId: newSku.skuId, count: oldGoods.count })
            })
            .then(() => {
              // 获取购物车列表(api)
              return findCart()
            })
            .then((data) => {
              // 设置购物车
              ctx.commit('setCart', data.result)
              resolve()
            })
        } else {
          // 未登录 本地
          // 1. 找出旧的商品信息
          // 2. 删除旧商品数据
          // 3. 根据新的sku信息和旧的商品信息，合并成一条新的购物车商品数据
          // 4. 添加新的商品

          // 当你修改了sku的时候其实skuId需要更改，相当于把原来的信息移出，创建一条新的商品信息。
          // 1. 获取旧的商品信息
          const oldGoods = ctx.state.list.find((item) => item.skuId === oldSkuId)
          // 2. 删除旧的商品
          ctx.commit('deleteCart', oldSkuId)
          // 3. 合并一条新的商品信息
          const { skuId, price: nowPrice, inventory: stock, specsText: attrsText } = newSku
          const newGoods = { ...oldGoods, skuId, nowPrice, stock, attrsText }
          // 4. 去插入即可
          ctx.commit('insertCart', newGoods)
        }
      })
    },
    // 7、合并本地购物车
    async mergeLocalCartActn(ctx) {
      // 存储token后调用合并API接口函数进行购物合并
      const cartList = ctx.getters.validList.map(({ skuId, selected, count }) => {
        return { skuId, selected, count }
      })
      // async/await 只有得到结果才会往下执行
      await mergeLocalCart(cartList)
      // 合并成功将本地购物车删除
      ctx.commit('setCart', [])
    }
  }
}
